import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException
import java.net.URLEncoder
import java.sql.Connection
import java.sql.DriverManager
import java.sql.SQLException

interface IpChangedListener {
    fun onIpChanged(urlIp: String, dnsIp: String?, dnspodIp: String?)
}

class DBIpChangedListener : IpChangedListener {
    companion object {
        const val DB_FILE = "ddns.db"
    }

    override fun onIpChanged(urlIp: String, dnsIp: String?, dnspodIp: String?) {
        var connection: Connection? = null
        try {
            // create a database connection
            connection = DriverManager.getConnection("jdbc:sqlite:${DB_FILE}")

            connection.createStatement().executeUpdate(
                """CREATE TABLE IF NOT EXISTS IP(
            URL_IP TEXT NOT NULL,
            DNS_IP TEXT,
            DNSPOD_IP TEXT,
            TIME BIGINT NOT NULL PRIMARY KEY);""".trimIndent()
            )

            connection.createStatement()
                .executeUpdate(
                    "INSERT INTO IP (URL_IP, DNS_IP, DNSPOD_IP, TIME) VALUES " +
                            "('$urlIp', ${dnsIp.wrap()}, ${dnspodIp.wrap()}, '${System.currentTimeMillis()}');"
                )
            Logger.i("store to db success")
        } catch (e: SQLException) {
            Logger.e(e)
        } finally {
            try {
                connection?.close()
            } catch (e: SQLException) {
                Logger.e(e)
            }
        }
    }

    private fun String?.wrap(): String {
        return if (isNullOrEmpty()) "NULL" else "'$this'"
    }
}

class WebhookIpChangedListener(private val url: String) : IpChangedListener {
    companion object {
        const val MAX_RETRY_COUNT = 10
    }
    private val client = OkHttpClient()

    override fun onIpChanged(urlIp: String, dnsIp: String?, dnspodIp: String?) {
        val msg = "ip changed\nurlIp: $urlIp\ndnsIp: $dnsIp\ndnspodIp: $dnspodIp"
        val url = url.replace("{msg}", URLEncoder.encode(msg, "UTF-8"))
        for (i in 1..MAX_RETRY_COUNT) {
            val result = tryRequest(url)
            if (result) {
                Logger.i("send to webhook")
                return
            }
            Thread.sleep(30000)
        }
        Logger.i("send to webhook fail")
    }

    private fun tryRequest(url: String) : Boolean {
        return try {
            val request = Request.Builder().url(url).build()
            val response = client.newCall(request).execute()
            response.isSuccessful
        } catch (e: IOException) {
            Logger.d(e)
            false
        }
    }

}